#include "driver/spi_master.h"
#include "esp_log.h"

#define FLASH_CS_IO    5     // Flash片选引脚
#define FLASH_MISO_IO  19    // Flash MISO引脚
#define FLASH_MOSI_IO  23    // Flash MOSI引脚
#define FLASH_CLK_IO   18    // Flash 时钟引脚

// 初始化SPI接口
void spi_flash_init() {
    spi_bus_config_t bus_config = {
        .sclk_io_num = FLASH_CLK_IO,  // CLK
        .mosi_io_num = FLASH_MOSI_IO, // MOSI
        .miso_io_num = FLASH_MISO_IO, // MISO
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
    };
    // 初始化SPI总线，配置SPI总线参数
    spi_bus_initialize(VSPI_HOST, &bus_config, 1);

    spi_device_handle_t spi;
    spi_device_interface_config_t devcfg = {
        .clock_speed_hz = 10 * 1000 * 1000, // SPI时钟频率：10MHz
        .mode = 0,  // SPI模式0
        .spics_io_num = FLASH_CS_IO,  // CS引脚
        .queue_size = 7, // 工作队列大小
    };
    // 挂载SPI设备
    spi_bus_add_device(VSPI_HOST, &devcfg, &spi);
}

// 读取Flash数据
void read_flash(uint32_t addr, uint8_t* out_data, size_t size) {
    esp_err_t ret;
    // 配置读取操作
    spi_transaction_t t;
    memset(&t, 0, sizeof(t));       // 清除交易结构体
    t.address = addr;                // 设置Flash地址
    t.length = size * 8;             // 设置要读取的数据长度（字节转位）
    t.rxlength = size * 8;          // 设置接收数据长度
    t.flags = SPI_TRANS_USE_RXDATA; // 标志：使用接收数据缓冲区

    // 发送读取命令并接收数据
    ret = spi_device_transmit(spi, &t);
    if (ret == ESP_OK) {
        memcpy(out_data, t.rx_data, size); // 复制数据到输出缓冲区
    } else {
        ESP_LOGE("SPI", "SPI transmit failed");
    }
}

void app_main() {
    // 初始化SPI Flash接口
    spi_flash_init();

    // 要读取的数据大小
    size_t size = 64;
    // 分配内存来存储读取的数据
    uint8_t data[size];

    // 从地址0x000000开始读取数据
    read_flash(0x000000, data, size);

    // 打印读取的数据
    for (int i = 0; i < size; i++) {
        printf("%02x ", data[i]);
        if ((i + 1) % 16 == 0) {
            printf("\n");
        }
    }
}